home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / Python-1.4 / Lib / site-python / ARexx.py next >
Text File  |  1998-06-24  |  5KB  |  210 lines

  1. """
  2. High level ARexx interface.
  3. ©1996 Irmen de Jong, disclaimer applies!
  4.  
  5. $VER: ARexx.py 1.2 (17.11.96)
  6. """
  7.  
  8. import arexxll
  9. import string
  10. import dos
  11. import sys
  12.  
  13. error = arexxll.error
  14.  
  15. errorstring = arexxll.errorstring
  16.  
  17. # ARexx result codes:
  18. RC_OK    =  0  # success
  19. RC_WARN  =  5  # warning only
  20. RC_ERROR = 10  # something's wrong
  21. RC_FATAL = 20  # complete or severe failure
  22.  
  23.  
  24. #### PORT #################################
  25.  
  26. class port:
  27.     """
  28.     ARexx port base class.
  29.     IMPORTANT: Don't create objects of this class directly, use one of
  30.     the derived classes below (publicport or privateport)!!!
  31.     """
  32.     def __init__(self,name):
  33.         self.port = arexxll.port(name)
  34.         self.signal = self.port.signal
  35.         if name:
  36.             self.name = self.port.name
  37.     def close(self):
  38.         self.port.close()
  39.     def wait(self):
  40.         self.port.wait()
  41.     def getmsg(self):
  42.         return self.port.getmsg()
  43.     def send(self,to,cmd,async=0):
  44.         self.flush()                        # XXX necessary?
  45.         if async:
  46.             self.port.send(to,cmd,1)        # no return value
  47.         else:
  48.             rc,rc2,result = self.port.send(to,cmd,0)
  49.             if rc:
  50.                 raise error, (rc,rc2)
  51.             else:
  52.                 return result
  53.     def flush(self):
  54.         while self.port.getmsg(): pass
  55.  
  56.  
  57. class privateport(port):
  58.     """
  59.     Private ARexx port.
  60.     Meant for sending messages to other ports only.
  61.     """
  62.     def __init__(self):
  63.         port.__init__(self,None)
  64.  
  65.     # currently, inherits all methods of port superclass unchanged
  66.  
  67.  
  68. class publicport(port):
  69.     """
  70.     Public ARexx port.
  71.     For setting up your own host.
  72.     """
  73.     def __init__(self,name='PYTHON'):
  74.         name=string.upper(name)
  75.         for c in name:
  76.             if not c in '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_.':
  77.                 raise ValueError,'invalid port name'
  78.         port.__init__(self,name)
  79.  
  80.     # currently, inherits all methods of port superclass unchanged
  81.  
  82.  
  83. #### HOST ##################################
  84.  
  85. class host(publicport):
  86.     """
  87.     ARexx host class.
  88.     For setting up your complete ARexx host system.
  89.     Automatic parsing & dispatching of command lines.
  90.     """
  91.     def __init__(self,name='PYTHON',cmds=None):
  92.         publicport.__init__(self,name)
  93.         self.commands = {}
  94.         self.setcommand('HELP','COMMAND,STEM/K,VAR/K',None,std_help_func)
  95.         self.cmderror='Unknown command'
  96.         self.catch = 0
  97.         if cmds: self.setcommands(cmds)
  98.     def __repr__(self):
  99.         if hasattr(self,'name'):
  100.             return '<host instance, port '+self.name+'>'
  101.         else:
  102.             return '<host instance, defunct>'
  103.     def close(self):
  104.         if hasattr(self,'port'):
  105.             self.port.close()
  106.             del self.name
  107.             del self.port
  108.             del self.commands
  109.     def setcommands(self,cmds):
  110.         for (c,t,d,f) in cmds:
  111.             self.setcommand(c,t,d,f)
  112.     def setcommand(self,cmd,template,defaults,func):
  113.         if template==None: parser=None
  114.         else: parser=dos.ArgParser(template)
  115.         self.commands[string.upper(cmd)]=(parser,func)
  116.         if defaults: self.setdefaults(cmd,defaults)
  117.     def setdefaults(self,cmd,defaults):
  118.         parser=self.commands[cmd][0]
  119.         if parser.defaults.keys()==defaults.keys():
  120.             parser.defaults=defaults
  121.         else:
  122.             raise ValueError,'incompatible defaults'
  123.     def defaults(self,cmd):
  124.         return self.commands[cmd][0].defaults
  125.     def catchExceptions(self,yes):
  126.         self.catch = yes
  127.     def dispatch(self):
  128.         m=self.port.getmsg()
  129.         res=-1
  130.         if m and m.msg:
  131.             i=string.index(m.msg+' ',' ')
  132.             cmd=string.upper(m.msg[:i])
  133.             args=m.msg[i+1:]
  134.             try:
  135.                 try:
  136.                     (parser,func) = self.commands[cmd]
  137.                 except KeyError:
  138.                     m.rc=RC_FATAL; m.rc2=self.cmderror
  139.                 else:
  140.                     if parser:
  141.                         res=func(self,m,cmd,parser.parse(args))
  142.                     else:
  143.                         res=func(self,m,cmd,args)
  144.             except dos.error,str:
  145.                 m.rc=RC_ERROR; m.rc2=str    # ReadArgs() probably failed
  146.             except:
  147.                 if self.catch:
  148.                     m.rc=RC_ERROR; m.rc2='Unhandled exception '+sys.exc_type+' : '+sys.exc_value
  149.                 else:
  150.                     print '*** Unhandled exception during ARexx cmd dispatch ***'
  151.                     raise sys.exc_type,sys.exc_value,sys.exc_traceback # re-raise exception
  152.             m.reply()
  153.         return res
  154.     def run(self):
  155.         self.flush()
  156.         while 1:
  157.             self.wait()
  158.             if not self.dispatch(): break
  159.     def flush(self):
  160.         while self.dispatch()!=-1: pass       # overrides publicport.flush
  161.  
  162.  
  163.  
  164. def std_help_func(host,msg,cmd,args):
  165.     var = args['VAR']
  166.     stem = args['STEM']
  167.     if args['COMMAND']:
  168.         try:
  169.             # return template for command
  170.             helpc=string.upper(args['COMMAND'])
  171.             parser=host.commands[helpc][0]
  172.             if parser:
  173.                 result=[parser.template]
  174.             else:
  175.                 result=['ARGS/F']
  176.         except KeyError:
  177.             msg.rc=RC_ERROR; msg.rc2='No help on command (unknown)'
  178.             return 1
  179.     else:
  180.         # return no. of commands followed by the commands.
  181.         cmds = host.commands.keys()
  182.         cmds.sort()
  183.         result = [`len(host.commands)`]+cmds
  184.     if var:
  185.         msg.setvar(var,string.join(result))
  186.     elif stem:
  187.         if len(result)==1:
  188.             msg.setvar(stem+'COUNT','1')
  189.             msg.setvar(stem+'1',result[0])
  190.         else:
  191.             msg.setvar(stem+'COUNT',result[0])
  192.             del result[0]
  193.             i=1
  194.             for c in result:
  195.                 msg.setvar(stem+`i`,c); i=i+1
  196.     else:
  197.         msg.result=string.join(result)
  198.     return 1
  199.  
  200. def std_debug_func(host,msg,cmd,args):
  201.     print 'DEBUG FUNCTION'
  202.     print 'HOST =',host
  203.     print 'MSG  =',msg
  204.     print 'CMD  =',cmd
  205.     print 'ARGS =',args
  206.     print 'RETURNING \'the result\''
  207.     msg.result='the result'
  208.     return 1
  209.  
  210.